/********************************************************
 *
 * File Name: PriorityLevel.java
 *
 * Purpose:
 *
 * Created By: 1337-Player-D
 * Date Created: Tuesday March 29, 2011.
 * Last Modified: Tuesday March 29, 2011.
 *
 ********************************************************/
package ca.utoronto.utm.csc301.euchre.player;

import java.util.List;
import java.util.ArrayList;
import ca.utoronto.utm.csc301.euchre.common.Rank;
import ca.utoronto.utm.csc301.euchre.common.Card;
import ca.utoronto.utm.csc301.euchre.common.Suit;

public class PriorityLevel {
    // Variables and Field(s)
    private Suit _preferredSuit;
    private List<Card> _cards;
    private List<Card> _topLevel;
    private List<Card> _lowerLevel;

    /****************************************************
     *               Constructor(s)
     ***************************************************/
    public PriorityLevel(List<Card> cards) {
        // Initialize Variables
        int bestChoice = 0;

        // Initialize Levels
        _cards = new ArrayList<Card>();
        _topLevel = new ArrayList<Card>();
        _lowerLevel = new ArrayList<Card>();

        // Load Cards into '_cards' Array
        for(int i=0; i<cards.size(); i++)
            _cards.add(cards.get(i));

        // Temp Variables
        int maxValue = 0;

        for(int i=0; i<_cards.size(); i++)
            switch(i){
                // Is Clubs is best Match?
                case 0:
                    // Rearrange Cards to Clubs
                    this.rearrangeTrump(Suit.CLUBS);

                    // Determine Value of Hand
                    if(maxValue < this.getValue(_topLevel))
                        maxValue = this.getValue(_topLevel);
                    
                    break;

                // Is Spades is best Match?
                case 1:
                    // Rearrange Cards to Spades
                    this.rearrangeTrump(Suit.SPADES);

                    // Determine Value of Hand
                    if(maxValue < this.getValue(_topLevel)){
                        bestChoice = 1;
                        maxValue = this.getValue(_topLevel);
                    }

                    break;

                // Is Hearts is best Match?
                case 2:
                    // Rearrange Cards to Hearts
                    this.rearrangeTrump(Suit.HEARTS);

                    // Determine Value of Hand
                    if(maxValue < this.getValue(_topLevel)){
                        bestChoice = 2;
                        maxValue = this.getValue(_topLevel);
                    }

                    break;

                // Is Diamonds is best Match?
                case 3:
                    // Rearragne Cards to Diamonds
                    this.rearrangeTrump(Suit.DIAMONDS);

                    // Determine Value of Hand
                    if(maxValue < this.getValue(_topLevel))
                        bestChoice = 3;

                    break;
                
            }
        
        // Set TopLevel as Largest Hit Count
        switch(bestChoice){
            // Clubs is best Match
            case 0:
                // Rearrange Cards to Clubs
                this.rearrangeTrump(Suit.CLUBS);
                break;

            // Spades is best Match
            case 1:
                // Rearrange Cards to Spades
                this.rearrangeTrump(Suit.SPADES);
                break;

            // Hearts is best Match
            case 2:
                // Rearrange Cards to Hearts
                this.rearrangeTrump(Suit.HEARTS);
                break;

            // Diamonds is best Match
            case 3:
                // Rearrange Cards to Diamonds
                this.rearrangeTrump(Suit.DIAMONDS);
                break;
        }
    }

    /****************************************************
     *              
     ***************************************************/
    public void rearrangeTrump(Suit suit) {
        // Initialize Variables
        _preferredSuit = suit;
        Suit oppositeSuit = null;

        // Clear Both Top and Lower Level
        _topLevel.clear();
        _lowerLevel.clear();

        // Determine Opposite Suit
        if(suit.isOfTheSameColor(Suit.CLUBS))
            oppositeSuit = Suit.SPADES;
        else if(suit.isOfTheSameColor(Suit.DIAMONDS))
            oppositeSuit = Suit.HEARTS;
        else if(suit.isOfTheSameColor(Suit.HEARTS))
            oppositeSuit = Suit.DIAMONDS;
        else if(suit.isOfTheSameColor(Suit.SPADES))
            oppositeSuit = Suit.CLUBS;

        // Find Left Bower and Add to Top Level
        for(int i=0; i<_cards.size(); i++){
            // Initialize Variable
            Card card = _cards.get(i);
            
            // Left/Right Bower add to TopLevel
            if(card.getRank() == Rank.JACK && (card.getSuit().isOfTheSameColor(suit) || card.getSuit().isOfTheSameColor(oppositeSuit)))
                _topLevel.add(card);
            else if(card.getSuit().isOfTheSameColor(suit))
                _topLevel.add(card);
            else
                _lowerLevel.add(card);
        }
    }

    /****************************************************
     *
     ***************************************************/
    public List<Card> topLevel() {
        // Returns TopLevel of Cards
        return _topLevel;
    }

    /****************************************************
     *
     ***************************************************/
    public List<Card> lowerLevel() {
        // Returns lowerLevel of Cards
        return _lowerLevel;
    }

    /****************************************************
     *
     ***************************************************/
    public Suit getPreferredSuit(){
        // Return Suit of TopLevel
        return _preferredSuit;
    }

    /****************************************************
     *
     ***************************************************/
    public List<Card> leadCards(Suit suit) {
        // Initialize Variables
        List<Card> tempCards = new ArrayList<Card>();

        // Search through MasterList and Select Cards with Same Suit
        for(int i=0; i<_cards.size(); i++)
            if(_cards.get(i).getSuit().isOfTheSameColor(suit))
                tempCards.add(_cards.get(i));

        // Return LeadCards
        return tempCards;
    }

    /****************************************************
     *
     ***************************************************/
    public void removeCard(Card card){
        // Remove Card from MasterList
        _cards.remove(card);

        // Remove Card from TopLevel or LowerLevel
        if(_topLevel.contains(card))
            _topLevel.remove(card);
        else
            _lowerLevel.remove(card);
    }

    /****************************************************
     *
     ***************************************************/
    public int getValue(List<Card> cards) {
        // Initialize Variables
        int maxValue = 0;

        // Loop Through Cards and Calculate Hand Rating
        for(int i=0; i<cards.size(); i++)
            maxValue += getRating(cards.get(i));

        // Return Value Calculated
        return maxValue;
    }
    /****************************************************
     *
     ***************************************************/
    private int getRating(Card card) {
        /*
        24 - jack of trump
        23 - jack of opposite color as trump
        22 - ace of trump
        21 - king of trump
        20 - queen of trump
        19 - 10 of trump
        18 - 9 of trump
        10 - all the rest
         */

        // Initialize Variables
        int rating = 10;
        Suit oppositeSuit = null;
        Suit suit = card.getSuit();
        Rank rank = card.getRank();
        
        // Determine Opposite Suit
        if(_preferredSuit.isOfTheSameColor(Suit.CLUBS))
            oppositeSuit = Suit.SPADES;
        else if(_preferredSuit.isOfTheSameColor(Suit.DIAMONDS))
            oppositeSuit = Suit.HEARTS;
        else if(_preferredSuit.isOfTheSameColor(Suit.HEARTS))
            oppositeSuit = Suit.DIAMONDS;
        else if(_preferredSuit.isOfTheSameColor(Suit.SPADES))
            oppositeSuit = Suit.CLUBS;

        // Determine if Card Given
        if (rank == Rank.JACK && suit.isOfTheSameColor(_preferredSuit))
            rating = 24;
        else if (rank == Rank.JACK && suit.isOfTheSameColor(oppositeSuit))
            rating = 23;
        else if (rank == Rank.ACE && suit.isOfTheSameColor(_preferredSuit))
            rating = 22;
        else if (rank == Rank.KING && suit.isOfTheSameColor(_preferredSuit))
            rating = 21;
        else if (rank == Rank.QUEEN && suit.isOfTheSameColor(_preferredSuit))
            rating = 20;
        else if (rank == Rank.TEN && suit.isOfTheSameColor(_preferredSuit))
            rating = 19;
        else if (rank == Rank.NINE && suit.isOfTheSameColor(_preferredSuit))
            rating = 18;

        // Return Card's Rating
        return rating;
    }
}
